/**
 * JAVACC DEMO 1.0
 */
package com.apache.portal.filter;

import com.apache.cache.util.Validator;
import com.apache.tools.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * description:  编码过滤器加安全验证
 *
 * @author Hou Dayu 创建时间：2016-8-13
 */
public class CharacterEncodingFilter implements Filter {

    protected String encoding = null;

    private Logger log = LoggerFactory.getLogger(CharacterEncodingFilter.class);

    private String[] inj_str = { "select ", "(select", "insert ", "drop ", "union ", "delete ",
            "update ", "+and+", " and ", "+or+", " or ", "<script", "confirm(", "prompt(", "eval(",
            "function(", ":alert", "alert(", "ltrim(", "[window[", "<iframe", "<a href", "<input ",
            "<img", "<audio", "onerror\\=", "ltrim(", "{tostring:", "</script", "</style",
            "/../" };//过滤掉的sql关键字，可以手动添加

    private String errorPage;

    private String writeStr;

    private static Pattern p;

    private static Matcher m;

    /**
     * TODO 简单描述该方法的实现功能（可选）.
     *
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
        encoding = null;
        errorPage = null;
    }

    /**
     * TODO 简单描述该方法的实现功能（可选）.
     *
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        String pui = req.getRequestURI();
        if (pui.toLowerCase().contains("/owa_util.signature") || pui.toLowerCase()
                .contains("/sqlnet.trc")) {
            log.warn("当前请求没有通过系统安会过滤");
            return;
        }

        if (filterPath(req)) {
            chain.doFilter(request, response);
            return;
        }

        String mothedType = req.getMethod();
        if ("post".equalsIgnoreCase(mothedType)) {
            if (Validator.isNotNull(request.getParameter("formToken"))) {
                chain.doFilter(request, response);
                return;
            }
        }
        String sql = req.getQueryString();
        if (StrUtil.isNull(sql)) {//获得所有请求参数名
            Enumeration<String> params = req.getParameterNames();
            while (params.hasMoreElements()) { //得到参数名
                String name = params.nextElement();
                String[] value = request.getParameterValues(name);
                for (int i = 0; i < value.length; i++) {
                    sql = sql + value[i];
                }
            }
        }
        if (StrUtil.isNotNull(sql)) {
            if (sql_inj(sql)) {
                log.warn("当前请求没有通过系统安会过滤,请求参数(param):" + sql);
                resp.sendRedirect(req.getContextPath() + errorPage);
                return;
            }
        }
        chain.doFilter(request, response);
    }

    /**
     * TODO 简单描述该方法的实现功能（可选）.
     *
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        encoding = filterConfig.getInitParameter("encoding");
        if (StrUtil.isNull(encoding))
            encoding = "UTF-8";
        errorPage = StrUtil.doNull(filterConfig.getInitParameter("errorPage"), "/common/error.jsp");
        writeStr = filterConfig.getInitParameter("writeStr");
    }

    private boolean filterPath(HttpServletRequest httpRequest) {

        String pui = httpRequest.getRequestURI();
        if (pui.contains(".css") || pui.contains("/js") || pui.contains("/images") || pui
                .contains("/web/CheckRandCode") || pui.contains("/weixin")) {
            //如果发现是css或者js文件，直接放行
            return true;
        }
        String toPage = httpRequest.getQueryString();
        if ("to=error".equals(toPage)) {
            return true;
        }
        if (null != writeStr) {
            String[] str = writeStr.split(",");
            for (int i = 0; i < str.length; i++) {
                if (pui.indexOf(str[i]) != -1) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean sql_inj(String str) {
        String sql = str.toLowerCase();
        sql = sql.replace("%28", "(").replace("%2b", "+").replace("%3c", "<").replace("%27", "'")
                .replace("%5b", "[").replace("%5d", "]").replace("%3d", "=").replace("%7c", "|")
                .replace("%7b", "{").replace("%3a", ":").replace("%2f", "/").replace("%2e", ".");
        for (int i = 0; i < inj_str.length; i++) {
            if (sql.indexOf(inj_str[i]) >= 0) {
                return true;
            }
        }
        return isEqualString(sql);
        //return false;
    }

    private boolean isEqualString(String str) {
        String regEx_style = "(<[a-zA-Z].*?>)|(<[\\/][a-zA-Z].*?>)";
        p = Pattern.compile(regEx_style);
        m = p.matcher(str);
        return m.matches();
    }
}
